# Lever 5 - pause deferrable background services # Each service resumes at the next boot. Stop only, never disable, never force. $eventLogSource = 'HighCPURemediationPauseServices' $eventLogName = 'Application' if (-not [System.Diagnostics.EventLog]::SourceExists($eventLogSource)) { New-EventLog -LogName $eventLogName -Source $eventLogSource -ErrorAction SilentlyContinue } function Write-RemediationEvent { param([string]$Message) Write-Output $Message try { Write-EventLog -LogName $eventLogName -Source $eventLogSource -EntryType Information -EventId 1000 -Message $Message -ErrorAction Stop } catch { # Tolerated. Losing an audit line must not stop remediation itself. } } # DiagTrack (Connected User Experiences and Telemetry) was removed from this # automatic, no-consent tier. Stopping it blinds endpoint diagnostics, and on # some configurations MDE telemetry, during the exact window a box is # misbehaving, for a marginal CPU saving. WSearch and SysMain are the real # wins here. If telemetry pausing is ever wanted, put it behind the consent # tier, not the silent one. $services = @('WSearch', 'SysMain', 'dosvc') foreach ($name in $services) { $svc = Get-Service -Name $name -ErrorAction SilentlyContinue if ($null -eq $svc) { continue } if ($svc.Status -ne 'Running') { continue } if (-not $svc.CanStop) { Write-RemediationEvent ('skip: {0} cannot be stopped' -f $name) continue } # Force is not used, so a service with live dependents is left running # rather than taking those dependents down with it. $dependents = @($svc.DependentServices | Where-Object { $_.Status -eq 'Running' }) if ($dependents.Count -gt 0) { Write-RemediationEvent ('skip: {0} has running dependents' -f $name) continue } $svc.Stop() Write-RemediationEvent ('paused: {0}' -f $name) }